package group.hhsw.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import group.hhsw.common.model.Product;
import group.hhsw.common.model.params.RateAndTerm;
import group.hhsw.common.model.params.SetAtomicParam;
import group.hhsw.common.model.params.SetProductParam;
import group.hhsw.common.model.vo.ProductVo;
import group.hhsw.product.mapper.ProductMapper;
import group.hhsw.product.service.ProductService;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.retry.RetryException;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.EnableRetry;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author hmj
 * @since 2022-02-03
 */
@Service
@EnableRetry
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService {

    @Autowired
    private ProductMapper productMapper;

    /**
     * 查询产品购买的限制区域
     *
     * @param id 产品id
     * @return 产品购买的限制区域
     */
    @Override
    public String productArea(@NotNull String id) {
        Product product = productMapper.selectOne(new LambdaQueryWrapper<Product>()
                .select(Product::getLimitArea)
                .eq(Product::getId, id));
        return product.getLimitArea();
    }

    /**
     * 添加原子服务
     *
     * @param setAtomicParam 修改产品原子服务参数
     * @return 影响行数
     */
    @Override
    public int addAtomic(@NotNull SetAtomicParam setAtomicParam) {
        return productMapper.update(null, new UpdateWrapper<Product>()
                .eq("id", setAtomicParam.getId())
                .set("service", setAtomicParam.getService()));
    }

    /**
     * 获得所有产品
     *
     * @return 产品list
     */
    @Override
    public List<ProductVo> getAll() {
        ArrayList<ProductVo> productVos = new ArrayList<>();
        List<Product> products = productMapper.selectList(new QueryWrapper<Product>());
        for (Product p : products) {
            String services = null;
            ProductVo productVo = new ProductVo();
            BeanUtils.copyProperties(p, productVo);
            if (productVo.getService().length() != 0) {
                services = "1," + productVo.getService() + ",10";
            } else {
                services = "1,10";
            }
            productVo.setService(services);
            productVos.add(productVo);
        }
        return productVos;
    }

    /**
     * 修改产品参数接口
     *
     * @param setProductParam 修改的产品参数
     * @return 影响行数
     */
    @Override
    public int updatePro(@NotNull SetProductParam setProductParam) {
        Product product = new Product();
        BeanUtils.copyProperties(setProductParam, product);
        return productMapper.update(product, new UpdateWrapper<Product>()
                .eq("id", setProductParam.getId()));
    }

    /**
     * 购买减少库存
     *
     * @param id 产品id
     * @return 影响行数
     */
    @Retryable(value = RetryException.class, maxAttempts = 3, backoff = @Backoff(delay = 2000L, multiplier = 1))
    @Override
    public int lockInventory(@NotNull String id) {
        Product product = productMapper.selectById(id);
        if (product.getAllowance() > 0) {
            //乐观锁减少库存
            int i = productMapper.update(null, new UpdateWrapper<Product>()
                    .set("allowance", product.getAllowance() - 1)
                    .eq("id", product.getId()));
            if (i == 0) throw new RetryException("商品库存减少失败");
            return i;
        }
        return 0;
    }

    /**
     * 获得商品原子服务编号
     *
     * @param id 商品id
     * @return 商品原子服务编号
     */
    @Override
    public String getProService(String id) {
        Product product = productMapper.selectOne(new LambdaQueryWrapper<Product>()
                .eq(Product::getId, id)
                .select(Product::getService));
        return product.getService();
    }

    /**
     * 获得产品期限
     * @param id 产品id
     * @return 期限
     */
    @Override
    public Integer getTerm(String id) {
        Product product = productMapper.selectOne(new LambdaQueryWrapper<Product>()
                .select(Product::getTerm)
                .eq(Product::getId, id));
        return product.getTerm();
    }

    /**
     * 获得产品利率和期限
     * @param id 产品id
     * @return 利率和期限
     */
    @Override
    public RateAndTerm getRateAndTerm(String id) {
        Product product = productMapper.selectById(id);
        RateAndTerm rateAndTerm = new RateAndTerm();
        BeanUtils.copyProperties(product, rateAndTerm);
        return rateAndTerm;
    }

    /**
     * 删除某个产品
     * @param id 产品id
     * @return 影响行数
     */
    @Override
    public Integer deletePro(String id) {
        return productMapper.deleteById(id);
    }

    /**
     * 根据产品id获取产品信息
     * @param id 产品id
     * @return 产品信息
     */
    @Override
    public List<ProductVo> getPro(String id) {
        Product product = productMapper.selectById(id);
        if (product == null) {
            return null;
        } else {
            ProductVo productVo = new ProductVo();
            ArrayList<ProductVo> list = new ArrayList<>();
            BeanUtils.copyProperties(product, productVo);
            list.add(productVo);
            return list;
        }
    }

    /**
     * 添加产品
     * @param setProductParam 产品信息
     * @return 影响行数
     */
    @Override
    public Integer addPro(SetProductParam setProductParam) {
        Product product = new Product();
        BeanUtils.copyProperties(setProductParam, product);
        product.setVersion(1);
        return productMapper.insert(product);
    }

    /**
     * 获取产品限额
     * @param id id
     * @return 限额
     */
    @Override
    public Long getSingePersonLimitAmount(String id) {
        Product product = productMapper.selectOne(new LambdaQueryWrapper<Product>()
                .select(Product::getLimitAmount)
                .eq(Product::getId, id));
        return product.getLimitAmount();
    }

    /**
     * 获取产品单日限额
     * @param id id
     * @return 单日限额
     */
    @Override
    public Long getSingeDayLimit(String id) {
        return productMapper.selectById(id).getDayLimitAmount();
    }
}
